//
// File:	Animation.cpp
// Author:	Thomas TISSOT-DUPONT
// E-mail:	<thomas.tissotdupont@free.fr>
// Create:	01/02/2010 21:20:29
// Purpose:	
//
#include "Base.hpp"
#include "DisplayManager.hpp"
#include "ResourceManager.hpp"
#include "ResourceManagerTypes.hpp"
#include "Animation.hpp"
#include "Util.hpp"
#include "Trace.hpp"

//------------------------------------------------------------------
// Constructor / Destructor
//------------------------------------------------------------------
Animation::Animation(	const sf::Image *pImage,
						const std::string &animName,
						const sf::Vector2i &ivFrameSize,
						float flFrameRate /* = 8.0f */,
						bool bFlipped /* = false */,
						bool bLoop /* = false */,
						int iRangeStart /* = -1 */,
						int iRangeEnd /* = -1 */)
	:	m_name(animName),
		m_flFrameRate(flFrameRate),
		m_ivFrameSize(ivFrameSize),
		m_bLoop(bLoop),
		m_bFlipped(bFlipped),
		m_bPlaying(false),
		m_flCurrentFrame(0.0f),
		m_framesVector(),
		m_clock()
{
	if (pImage == NULL)
		return;
	
	//Frames
	int nFramesX = pImage->GetWidth() / m_ivFrameSize.x;
	int nFramesY = pImage->GetHeight() / m_ivFrameSize.y;
	int y = 0;
	for (int nFrames = nFramesX * nFramesY; nFrames > 0; nFrames -= nFramesX)
	{
		for (int x = m_ivFrameSize.x * (nFramesX - 1); x >= 0; x -= m_ivFrameSize.x)
		{
			Frame frame;
			frame.top = y;
			frame.left = x;
			frame.right = x + m_ivFrameSize.x;
			frame.bottom = y + m_ivFrameSize.y;
			m_framesVector.push_back(frame);
		}
		y += m_ivFrameSize.y;
	}

	//Flip
	if (bFlipped)
	{
		std::vector<Frame> copy(m_framesVector);
		m_framesVector.clear();
		std::vector<Frame>::reverse_iterator rit = copy.rbegin();
		std::vector<Frame>::reverse_iterator rite = copy.rend();
		for (; rit != rite; ++rit)
		{
			m_framesVector.push_back(*rit);
		}
	}

	//Range (not optimized)
	iRangeStart = util::min(iRangeStart, nFramesX * nFramesY - 1);
	iRangeEnd = util::min(iRangeEnd, nFramesX * nFramesY - 1);
	if (iRangeStart > -1 && iRangeEnd > -1 && iRangeStart <= iRangeEnd)
	{
		for (int i = 0; i < iRangeStart; i++)
		{
			m_framesVector.erase(m_framesVector.begin());
		}
		for (int i = nFramesX * nFramesY - 1; i > iRangeEnd; i--)
		{
			m_framesVector.pop_back();
		}
	}
}

Animation::~Animation()
{
}

//------------------------------------------------------------------
// Play / Stop
//------------------------------------------------------------------
void Animation::Play()
{
	m_bPlaying = true;
	m_clock.Reset();
}

void Animation::Pause()
{
	m_bPlaying = false;
}

void Animation::Stop()
{
	m_bPlaying = false;
	m_flCurrentFrame = 0.0f;
}

//------------------------------------------------------------------
// Update
//------------------------------------------------------------------
void Animation::Update()
{
	if (m_framesVector.size() > 0 && m_bPlaying)
	{
		m_flCurrentFrame += GlobalVariables::Global::Get().GetFrameTime() * m_flFrameRate;
		if (static_cast<unsigned int>(m_flCurrentFrame) >= m_framesVector.size())
		{
			if (m_bLoop == false)
			{
				Pause(); //HACK
				m_flCurrentFrame = m_framesVector.size() - 1;
				emit OnAnimationFinished(this);
			}
			else
			{
				m_flCurrentFrame = 0;
				emit OnAnimationLooped(this);
			}
		}
	}
}

//------------------------------------------------------------------
// Frame Rate
//------------------------------------------------------------------
void Animation::SetFrameRate(float flFrameRate)
{
	m_flFrameRate = flFrameRate;
}

//------------------------------------------------------------------
// Loop / Flip
//------------------------------------------------------------------
void Animation::SetLoop(bool bLoop)
{
	m_bLoop = bLoop;
}

void Animation::SetFlipped(bool bFlipped)
{
	m_bFlipped = bFlipped;
}

//------------------------------------------------------------------
// Name
//------------------------------------------------------------------
const std::string &Animation::GetName() const
{
	return m_name;
}

//------------------------------------------------------------------
// Is Playing ?
//------------------------------------------------------------------
bool Animation::IsPlaying() const
{
	return m_bPlaying;
}

//------------------------------------------------------------------
// Current Frame
//------------------------------------------------------------------
const Animation::Frame *Animation::GetCurrentFrame() const
{
	if (m_framesVector.empty())
		return NULL;
	return &m_framesVector[static_cast<unsigned int>(m_flCurrentFrame)];
}
